﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using intelliPaper.Model;
using intelliPaper.DB.AccessUtil;
using System.Data.SqlClient;
using System.Data;

namespace intelliPaper.DB
{
    public class Dao
    {

        /// <summary>
        /// 向数据库中添加一个知识点
        /// </summary>
        /// <param name="knowledgePoint">要添加的知识点，知识点的属性应该完全</param>
        /// <returns>返回该知识点的数据库中的ID号</returns>
        static public int AddKnowledgePoint(KnowledgePoint knowledgePoint)
        {
            DBConnection dbConnection = new DBConnection();
            int identity;

            //添加知识点
            Dictionary<string, object> dictionary = new Dictionary<string, object>();
            dictionary.Add("body", knowledgePoint.KnowledgePointBody);
            dictionary.Add("importance", knowledgePoint.Importance);
            dictionary.Add("difficulty", knowledgePoint.KnowledgeDifficulty);
            dictionary.Add("isopenxmlenabled", knowledgePoint.IsOpenXMLEnabled);
            if (dbConnection.Insert(dictionary, "knowledgepoint"))
            {
                //获得添加的知识的点的ID
                identity = dbConnection.GetIdentity();
                //提交事务
                dbConnection.CommitTransaction();
                return identity;
            }
            else
            {
                return -1;
            }

        }
        /// <summary>
        /// 向数据库中添加一个题目
        /// </summary>
        /// <param name="question">要添加的题目，题目的属性应该完全</param>
        /// <returns>返回题目的数据库中的ID号</returns>
        static public int AddQuestion(Question question)
        {
            DBConnection dbConnection = new DBConnection();
            int identity;

            //添加题干
            Dictionary<string, object> dictionary = new Dictionary<string, object>();
            dictionary.Add("questiontype", question.QuestionType);
            dictionary.Add("importance", question.StartDifficulty);
            //dictionary.Add("createdate", question.HistoryMessage.FoundTime);
            dictionary.Add("body", question.QuestionBody);
            dictionary.Add("isopenxmlenabled", question.IsOpenXMLEnabled);
            dictionary.Add("difficulty", question.StartDifficulty);
            dictionary.Add("summary", question.Summary);

            dictionary.Add("createdate", DateTime.Now.AddYears(-3).Date);

            if (dbConnection.Insert(dictionary, "questionbody"))
            {
                //添加答案
                //得到题干的id号
                identity = dbConnection.GetIdentity();
                //添加正确答案
                List<Dictionary<string, object>> trueAnswers = new List<Dictionary<string, object>>();
                foreach (string s in question.TrueAnswers)
                {
                    Dictionary<string, object> dic = new Dictionary<string, object>();
                    dic.Add("body", s);
                    dic.Add("trueorfalse", true);
                    dic.Add("questionid", identity);
                    trueAnswers.Add(dic);
                }
                dbConnection.Insert(trueAnswers, "answer");

                //添加错误答案
                List<Dictionary<string, object>> falseAnswers = new List<Dictionary<string, object>>();
                foreach (string s in question.ErrorAnswers)
                {
                    Dictionary<string, object> dic = new Dictionary<string, object>();
                    dic.Add("body", s);
                    dic.Add("trueorfalse", false);
                    dic.Add("questionid", identity);
                    falseAnswers.Add(dic);
                }
                dbConnection.Insert(falseAnswers, "answer");

                //将题目和知识点之间的关系添加到相应的表中
                List<Dictionary<string, object>> knowledgePoints = new List<Dictionary<string, object>>();
                foreach (KnowledgePoint kp in question.KnowledgePoints)
                {
                    Dictionary<string, object> dic = new Dictionary<string, object>();
                    dic.Add("questionid", identity);
                    dic.Add("knowledgepointid", kp.ID);
                    knowledgePoints.Add(dic);
                }
                dbConnection.Insert(knowledgePoints, "question_knowledgepoint");


                //提交事务
                dbConnection.CommitTransaction();

                return identity;
            }
            else
            {
                return -1;
            }

        }
        /// <summary>
        /// 为题目添加一个历史信息
        /// </summary>
        /// <param name="question">目标题目，至少应该有ID号</param>
        /// <param name="historyMessage">要添加的历史信息，历史信息的属性应该完全</param>
        /// <returns>是否添加成功</returns>
        static public bool AddQuestionHistroyMessage(Question question, HistoryMessage historyMessage)
        {
            DBConnection dbConn = new DBConnection();
            Dictionary<string, object> dictionary = new Dictionary<string, object>();
            dictionary.Add("errorrate", historyMessage.ErrorRate);
            dictionary.Add("belongsto", "题目");
            dictionary.Add("belongstoid", question.ID);
            dictionary.Add("recorddate", historyMessage.RecordDate);

            if (dbConn.Insert(dictionary, "historymessage"))
            {
                dbConn.CommitTransaction();
                return true;
            }
            else
            {
                return false;
            }


        }
        /// <summary>
        /// 为知识点添加一个历史信息
        /// </summary>
        /// <param name="knowledgePoint">目标知识点，至少应该有ID号</param>
        /// <param name="historyMessage">要添加的历史信息，历史信息的属性应该完全</param>
        /// <returns>是否添加成功</returns>
        static public bool AddKnowledgePointHistoryMessage(KnowledgePoint knowledgePoint, HistoryMessage historyMessage)
        {
            DBConnection dbConn = new DBConnection();
            Dictionary<string, object> dictionary = new Dictionary<string, object>();
            dictionary.Add("errorrate", historyMessage.ErrorRate);
            dictionary.Add("belongsto", "知识点");
            dictionary.Add("belongstoid", knowledgePoint.ID);
            dictionary.Add("recorddate", historyMessage.RecordDate);

            if (dbConn.Insert(dictionary, "historymessage"))
            {
                dbConn.CommitTransaction();
                return true;
            }
            else
            {
                return false;
            }

        }
        /// <summary>
        /// 私有，设置知识点的可用性
        /// </summary>
        /// <param name="knowledgePoint">目标知识点，至少要有ID号</param>
        /// <param name="isenabled">是否可用</param>
        /// <returns>是否成功</returns>
        static private bool SetKnowledgePointEnabled(KnowledgePoint knowledgePoint, bool isenabled)
        {
            DBConnection dbConn = new DBConnection();
            Dictionary<string, object> dic = new Dictionary<string, object>();
            dic.Add("isenabled", isenabled);
            Dictionary<string, object> dic2 = new Dictionary<string, object>();
            dic2.Add("id", knowledgePoint.ID);

            bool result = dbConn.Update(dic, dic2, "knowledgepoint");

            dbConn.CommitTransaction();
            return result;
        }
        /// <summary>
        /// 删除知识点，但可见
        /// </summary>
        /// <param name="knowledgePoint">目标知识点，至少应该有ID号</param>
        /// <returns>是否成功</returns>
        static public bool DeleteKnowledgePoint(KnowledgePoint knowledgePoint)
        {
            return SetKnowledgePointEnabled(knowledgePoint, false);
        }
        /// <summary>
        /// 复原知识点
        /// </summary>
        /// <param name="knowledgePoint">目标知识点，至少应该有ID号</param>
        /// <returns>是否成功</returns>
        static public bool RecoverKnowledgePoint(KnowledgePoint knowledgePoint)
        {
            return SetKnowledgePointEnabled(knowledgePoint, true);
        }
        /// <summary>
        /// 私有，设置题目的可用性
        /// </summary>
        /// <param name="question">目标题目，至少要有ID号</param>
        /// <param name="isenabled">是否可用</param>
        /// <returns>是否成功</returns>
        static private bool SetQuestionEnabled(Question question, bool isenabled)
        {
            DBConnection dbConn = new DBConnection();
            Dictionary<string, object> values = new Dictionary<string, object>();
            values.Add("isenabled", isenabled);
            Dictionary<string, object> conditions = new Dictionary<string, object>();
            conditions.Add("id", question.ID);

            bool result = dbConn.Update(values, conditions, "questionbody");
            dbConn.CommitTransaction();

            return result;
        }
        /// <summary>
        /// 删除题目，但可见
        /// </summary>
        /// <param name="question"></param>
        /// <returns></returns>
        static public bool DeleteQuestion(Question question)
        {
            return SetQuestionEnabled(question, false);
        }
        /// <summary>
        /// 复原题目
        /// </summary>
        /// <param name="question">目标知识点，至少要有ID号</param>
        /// <returns>是否成功</returns>
        static public bool RecoverQuestion(Question question)
        {
            return SetQuestionEnabled(question, true);
        }
        /// <summary>
        /// 获取数据库中所有的知识点，包括已经删除的
        /// </summary>
        /// <returns>所有的知识点</returns>
        static public List<KnowledgePoint> GetAllKnowledgePoints()
        {
            DBConnection dbConn = new DBConnection();
            string sqlString = "select * from knowledgepoint";

            //存储返回的列名和元数据
            List<Dictionary<string, object>> knowledgePointsmeta = dbConn.SelectToList(sqlString);
            List<KnowledgePoint> knowledgePoints = new List<KnowledgePoint>();
            if (knowledgePointsmeta != null)
            {

                foreach (Dictionary<string, object> dic in knowledgePointsmeta)
                {
                    KnowledgePoint kp = new KnowledgePoint();
                    kp.CreateDate = Convert.ToDateTime(dic["createdate"]);
                    kp.SetID(Convert.ToInt32(dic["id"]));
                    kp.Importance = Convert.ToDouble(dic["importance"]);
                    kp.KnowledgeDifficulty = Convert.ToDouble(dic["difficulty"]);
                    kp.KnowledgePointBody = Convert.ToString(dic["body"]);
                    kp.IsEnabled = Convert.ToBoolean(dic["isenabled"]);
                    kp.UseFrequency = Convert.ToInt32(dic["usefrequency"]);
                    kp.IsOpenXMLEnabled = Convert.ToBoolean(dic["isopenxmlenabled"]);

                    knowledgePoints.Add(kp);
                }


            }
            return knowledgePoints;

        }
        /// <summary>
        /// 将所有的知识点放在知识点字典里，键为知识点的ID号
        /// </summary>
        /// <returns>知识点字典</returns>
        static public Dictionary<int, KnowledgePoint> GetAllKnowledgePointsDictionary()
        {
            List<KnowledgePoint> ks = GetAllKnowledgePoints();
            Dictionary<int, KnowledgePoint> d = new Dictionary<int, KnowledgePoint>();
            foreach (KnowledgePoint k in ks)
            {
                d.Add(k.ID, k);
            }

            return d;
        }
        /// <summary>
        /// 获取所有的题目，包括已经删除的
        /// </summary>
        /// <returns>所有的题目</returns>
        static public List<Question> GetAllQuestions()
        {
            DBConnection dbConn = new DBConnection();

            string sqlString = "select q.id as qid,q.body as qbody,q.questiontype as qtype,q.importance as qimportance,q.isopenxmlenabled as qisopenxmlenabled,q.difficulty as qdifficulty,q.createdate as qcreatedate,q.lastusedate as qlastusedate,q.usefrequency as qusefrequency,q.isenabled as qisenabled, q.summary as qsummary from questionbody as q";

            //存储返回的列名称和相应的值
            List<Dictionary<string, object>> questionsmeta = dbConn.SelectToList(sqlString);
            //存储最终的题目
            List<Question> questions = new List<Question>();
            if (questionsmeta != null)
            {


                //查找所有的题目
                foreach (Dictionary<string, object> dic in questionsmeta)
                {
                    //根据列名
                    Question question = new Question();
                    question.CreateDate = Convert.ToDateTime(dic["qcreatedate"]);
                    question.SetID(Convert.ToInt32(dic["qid"]));
                    question.LastUsed = Convert.ToDateTime(dic["qlastusedate"]);


                    //question.QuestionBody = Convert.ToString(dic["qbody"]);

                    //判断是不是从access里取出来的
                    //如果是从access里取出来的，大数据块是用二进制数组byte[]存的，所以要转化一下
                    //是Unicode
                    if (dic["qbody"].GetType() == typeof(Byte[]))
                    {
                        question.QuestionBody = Encoding.Unicode.GetString((Byte[])dic["qbody"]);
                    }
                    else
                    {
                        question.QuestionBody = Convert.ToString(dic["qbody"]);
                    }


                    question.QuestionType = Convert.ToString(dic["qtype"]);
                    question.StartDifficulty = Convert.ToDouble(dic["qdifficulty"]);
                    question.UseFrequency = Convert.ToInt32(dic["qusefrequency"]);
                    question.IsEnabled = Convert.ToBoolean(dic["qisenabled"]);
                    question.IsOpenXMLEnabled = Convert.ToBoolean(dic["qisopenxmlenabled"]);
                    question.Summary = Convert.ToString(dic["qsummary"]);

                    //查找每个问题的答案
                    sqlString = string.Format("select a.body as abody,trueorfalse,a.id as aid from answer as a where questionid={0}", question.ID.ToString());
                    //列名称和相应的答案的值
                    List<Dictionary<string, object>> answersmeta = dbConn.SelectToList(sqlString);
                    //将答案添加到题目的相应属性中
                    //其中，根据数据库中存储的答案中的 “trueorfalse” 域来决定该答案是正确答案还是错误答案
                    //如果是正确答案，则存储到题目中的TrueAnswers里，否则存储在ErrorAnswers里
                    if (answersmeta != null)
                    {
                        foreach (Dictionary<string, object> dic2 in answersmeta)
                        {
                            if (Convert.ToBoolean(dic2["trueorfalse"]))
                            {
                                question.TrueAnswers.Add(Convert.ToString(dic2["abody"]));
                            }
                            else
                            {
                                question.ErrorAnswers.Add(Convert.ToString(dic2["abody"]));
                            }
                        }
                    }


                    //获得该题目所关联的知识点
                    //在这里需要考虑，是不是通过这里的再次查询，因为我们在程序运行过程中可能需要整套的知识点，
                    //那是必须查询的，所以我们可以确定我们的程序中肯定已经有一套知识点，所以不建议在这里查询所有的知识点，而是到那一整套里去查询
                    //但这里需要给出相应知识点的ID号这倒是真的 

                    sqlString = string.Format("select * from question_knowledgepoint where questionid={0}", question.ID);

                    using (DataTable dt = dbConn.Select(sqlString))
                    {
                        if (dt != null && dt.Rows != null && dt.Rows.Count > 0)
                        {
                            foreach (DataRow dr in dt.Rows)
                            {
                                KnowledgePoint kp = new KnowledgePoint();
                                kp.SetID(Convert.ToInt32(dr["knowledgepointid"]));
                                question.KnowledgePoints.Add(kp);
                            }
                        }
                    }

                    //获得所有的历史信息
                    sqlString = string.Format("select * from historymessage where belongsto='题目' and belongstoid={0}", question.ID);
                    List<Dictionary<string, object>> historymessagemeta = dbConn.SelectToList(sqlString);
                    if (historymessagemeta != null)
                    {
                        foreach (Dictionary<string, object> dic2 in historymessagemeta)
                        {
                            HistoryMessage historymessage = new HistoryMessage();
                            historymessage.ErrorRate = Convert.ToInt32(dic2["errorrate"]);
                            historymessage.RecordDate = Convert.ToDateTime(dic2["recorddate"]);
                            question.HistoryMessages.Add(historymessage);
                        }
                    }
                    questions.Add(question);
                }

            }
            return questions;


        }
        /// <summary>
        /// 获取题目字典
        /// </summary>
        /// <returns>题目字典，键为题目的ID号</returns>
        static public Dictionary<int, Question> GetAllQuestionsDictionary()
        {
            List<Question> questions = GetAllQuestions();
            Dictionary<int, Question> dictionary = new Dictionary<int, Question>();
            foreach (Question q in questions)
            {
                dictionary.Add(q.ID, q);
            }
            return dictionary;
        }
        /// <summary>
        /// 使用了这个问题，就修改最后使用时间，增加使用频率
        /// </summary>
        /// <param name="question"></param>
        /// <returns></returns>
        static public bool UseQuestion(Question question)
        {
            DBConnection dbConn = new DBConnection();
            Dictionary<string, object> values = new Dictionary<string, object>();
            values.Add("lastusedate", DateTime.Now);
            values.Add("usefrequency", question.UseFrequency + 1);
            Dictionary<string, object> conditions = new Dictionary<string, object>();
            conditions.Add("id", question.ID);
            bool result = dbConn.Update(values, conditions, "questionbody");

            foreach (KnowledgePoint kp in question.KnowledgePoints)
            {
                values.Clear();
                values.Add("usefrequency", kp.UseFrequency + 1);
                conditions.Clear();
                conditions.Add("id", kp.ID);
                dbConn.Update(values, conditions, "knowledgepoint");
            }


            dbConn.CommitTransaction();

            return result;
        }
        /// <summary>
        /// 向数据库中添加一个试卷
        /// </summary>
        /// <param name="paper">要添加的试卷，试卷的属性应该完全</param>
        /// <returns>返回试卷在数据库的ID号</returns>
        static public int AddPaper(Paper paper)
        {
            DBConnection dbConn = new DBConnection();
            int identity = 0;

            Dictionary<string, object> dictionary = new Dictionary<string, object>();
            dictionary.Add("testdate", paper.TestDate);
            dictionary.Add("introduction", paper.Introduction);
            dictionary.Add("difficulty", paper.Difficulty);
            //dictionary.Add("lastmodifydate", paper.LastModifyDate);
            dictionary.Add("isenabled", paper.IsEnabled);

            if (dbConn.Insert(dictionary, "paper"))
            {
                identity = dbConn.GetIdentity();
                foreach (Question q in paper.Questions)
                {
                    dictionary.Clear();
                    dictionary.Add("paperid", identity);
                    dictionary.Add("questionid", q.ID);
                    if (dbConn.Insert(dictionary, "paper_question"))
                    {
                        Dictionary<string, object> values = new Dictionary<string, object>();
                        values.Add("lastusedate", DateTime.Now);
                        values.Add("usefrequency", q.UseFrequency + 1);
                        Dictionary<string, object> conditions = new Dictionary<string, object>();
                        conditions.Add("id", q.ID);
                        bool result = dbConn.Update(values, conditions, "questionbody");

                        foreach (KnowledgePoint kp in q.KnowledgePoints)
                        {
                            values.Clear();
                            values.Add("usefrequency", kp.UseFrequency + 1);
                            conditions.Clear();
                            conditions.Add("id", kp.ID);
                            dbConn.Update(values, conditions, "knowledgepoint");
                        }
                    }
                }
                dbConn.CommitTransaction();

                return identity;
            }
            else
            {
                return -1;
            }

        }
        /// <summary>
        /// 获取所有的试卷，包括已经删除的
        /// </summary>
        /// <returns>所有的试卷</returns>
        static public List<Paper> GetAllPapers()
        {
            DBConnection dbConn = new DBConnection();
            string sqlString = "select * from paper";

            List<Dictionary<string, object>> papermeta = dbConn.SelectToList(sqlString);
            List<Paper> papers = new List<Paper>();
            if (papermeta != null)
            {

                foreach (Dictionary<string, object> dic in papermeta)
                {
                    Paper paper = new Paper();
                    paper.SetID(Convert.ToInt32(dic["id"]));
                    paper.IsEnabled = Convert.ToBoolean(dic["isenabled"]);
                    paper.Introduction = Convert.ToString(dic["introduction"]);
                    paper.LastModifyDate = Convert.ToDateTime(dic["lastmodifydate"]);
                    paper.TestDate = Convert.ToDateTime(dic["testdate"]);
                    paper.Difficulty = Convert.ToDouble(dic["difficulty"]);

                    sqlString = string.Format("select * from paper_question where paperid={0}", paper.ID);

                    List<Dictionary<string, object>> questionmeta = dbConn.SelectToList(sqlString);

                    if (questionmeta != null)
                    {
                        foreach (Dictionary<string, object> dic2 in questionmeta)
                        {
                            Question question = new Question();
                            question.SetID(Convert.ToInt32(dic2["questionid"]));
                            paper.Questions.Add(question);
                        }
                    }

                    papers.Add(paper);
                }


            }
            return papers;


        }
        /// <summary>
        /// 获取试卷字典
        /// </summary>
        /// <returns>或许试卷字典，键为试卷的ID号</returns>
        static public Dictionary<int, Paper> GetAllPapersDictionary()
        {
            List<Paper> ps = GetAllPapers();
            Dictionary<int, Paper> d = new Dictionary<int, Paper>();
            foreach (Paper p in ps)
            {
                d.Add(p.ID, p);
            }

            return d;
        }
        /// <summary>
        /// 设置试卷的可用性
        /// </summary>
        /// <param name="paper">目标试卷</param>
        /// <param name="isenabled">是否可用</param>
        /// <returns>是否成功</returns>
        static private bool SetPaperEnabled(Paper paper, bool isenabled)
        {
            DBConnection dbConn = new DBConnection();
            Dictionary<string, object> values = new Dictionary<string, object>();
            values.Add("isenabled", isenabled);
            Dictionary<string, object> conditions = new Dictionary<string, object>();
            conditions.Add("id", paper.ID);

            bool result = dbConn.Update(values, conditions, "paper");
            dbConn.CommitTransaction();

            return result;
        }
        /// <summary>
        /// 删除试卷，但可见
        /// </summary>
        /// <param name="paper">目标试卷，至少应该有ID号</param>
        /// <returns>是否成功</returns>
        static public bool DeletePaper(Paper paper)
        {
            return SetPaperEnabled(paper, false);
        }
        /// <summary>
        /// 复原试卷
        /// </summary>
        /// <param name="paper">目标试卷，至少应该有ID号</param>
        /// <returns>是否成功</returns>
        static public bool RecoverPaper(Paper paper)
        {
            return SetPaperEnabled(paper, true);
        }






    }

    public static class Helper
    {
        public static bool StringCollectionEqual(IEnumerable<string> collection, IEnumerable<string> other)
        {
            if (collection.Count() != other.Count())
            {
                return false;
            }
            foreach (string key in collection)
            {
                if (!other.Contains<string>(key))
                {
                    return false;
                }
            }
            return true;
        }
        /// <summary>
        /// 填充题目列表中每个题目的知识点（初始化辅助函数）
        /// </summary>
        /// <param name="allkps">数据库中所有的知识点列表</param>
        /// <param name="allqs">要填充的题目列表，应有知识点的ID号列表</param>
        static public void InitialKnowledgePointInQuestions(List<KnowledgePoint> allkps, List<Question> allqs)
        {
            Dictionary<int, KnowledgePoint> ks = new Dictionary<int, KnowledgePoint>();
            if (allkps == null)
                return;
            foreach (KnowledgePoint k in allkps)
            {
                ks.Add(k.ID, k);
            }


            for (int i = 0; i < allqs.Count; i++)
            {
                for (int j = 0; j < allqs[i].KnowledgePoints.Count; j++)
                {
                    allqs[i].KnowledgePoints[j] = ks[allqs[i].KnowledgePoints[j].ID];
                }
            }
        }
        /// <summary>
        /// 填充题目（初始化辅助函数）
        /// </summary>
        /// <param name="allquestions">所有的知识点列表</param>
        /// <param name="targetquestions">要填充的题目列表，应有题目的ID号</param>
        static public void FillQuestions(List<Question> allquestions, List<Question> targetquestions)
        {

            for (int i = 0; i < targetquestions.Count; i++)
            {
                int id = targetquestions[i].ID;
                targetquestions[i] = allquestions.Find(new Predicate<Question>(delegate(Question q1)
                {
                    if (q1.ID == id)
                        return true;
                    else return false;

                }));
            }
        }
        /// <summary>
        /// 填充知识点（初始化辅助函数）
        /// </summary>
        /// <param name="allknowledgepoints">所有的知识点列表</param>
        /// <param name="targetknowledgepoints">要填充的知识点列表，应有知识点的ID号列表</param>
        static public void FillKnowledgePoints(List<KnowledgePoint> allknowledgepoints, List<KnowledgePoint> targetknowledgepoints)
        {
            for (int i = 0; i < targetknowledgepoints.Count; i++)
            {
                int id = targetknowledgepoints[i].ID;
                targetknowledgepoints[i] = allknowledgepoints.Find(new Predicate<KnowledgePoint>(delegate(KnowledgePoint k)
                {
                    if (k.ID == id)
                        return true;
                    else
                        return false;

                }));
            }
        }


        static public void GetPossibility(Question question)
        {
            double possibility = 0;
            int frequency = 0;
            foreach (HistoryMessage hm in question.HistoryMessages)
            {
                possibility += ((double)hm.ErrorRate) / 100;
            }
            possibility /= question.HistoryMessages.Count;

            foreach (KnowledgePoint k in question.KnowledgePoints)
            {
                frequency += k.UseFrequency;
            }

            question.Possiblity = (question.StartDifficulty + possibility) / frequency;
        }


        static public bool CheckBoolArray(bool[] array)
        {
            bool result = true;
            foreach (bool b in array)
            {
                if (!b)
                {
                    return false;
                }
                result = result && b;
            }
            return result;
        }

        /// <summary>
        /// 获得自动组卷的试题列表
        /// </summary>
        /// <param name="questionBase">所有的试题列表</param>
        /// <param name="knowledgePointBase">要覆盖的知识点列表</param>
        /// <param name="request">试题类型和试题数目字典</param>
        /// <returns>尽可能的覆盖知识点的试题列表，如果不能覆盖，返回的列表试题总数可能小于要求的数量</returns>
        static public List<Question> AutoMakePaper(List<Question> questionBase, List<KnowledgePoint> knowledgePointBase, Dictionary<string, int> request)
        {

            List<Question> result = new List<Question>();
            Dictionary<KnowledgePoint, List<Question>> questionsRelatedToK = new Dictionary<KnowledgePoint, List<Question>>();
            KnowledgePoint[] ks = new KnowledgePoint[knowledgePointBase.Count];

            knowledgePointBase.CopyTo(ks);

            List<KnowledgePoint> knowledgePointsGiven = ks.ToList();


            //以知识点为键值，添加到字典中，字典的值是知识点所对应的题目集合
            foreach (KnowledgePoint k in knowledgePointBase)
            {
                questionsRelatedToK.Add(k, new List<Question>());
            }

            //将题目添加到字典中
            foreach (Question q in questionBase)
            {
                GetPossibility(q);
                foreach (KnowledgePoint k in q.KnowledgePoints)
                {
                    if (questionsRelatedToK.Keys.Contains(k))
                    {
                        questionsRelatedToK[k].Add(q);
                    }
                }
            }

            foreach (KnowledgePoint k in questionsRelatedToK.Keys)
            {
                questionsRelatedToK[k].Sort(((o, p) => { return o.Possiblity.CompareTo(p.Possiblity); }));
            }

            //让字典按照知识点对应的题型的数目排序,提醒数目相同的，按照题目的数量排序
            questionsRelatedToK.OrderBy<KeyValuePair<KnowledgePoint, List<Question>>, List<Question>>(o => { return o.Value; }, new QuestionTypeNumberComparer());

            //记录题型是不是已经全部填充完毕
            Dictionary<string, bool> flags = new Dictionary<string, bool>();
            Dictionary<string, int> questionnumbers = new Dictionary<string, int>();
            for (int i = 0; i < request.Count; i++)
            {
                flags.Add(request.Keys.ToArray()[i], false );
                questionnumbers.Add(request.Keys.ToArray()[i], 0);
            }

            bool allqdone = false;

            while (true  )
            {
                foreach (KnowledgePoint k in knowledgePointsGiven)
                {
                    if (questionsRelatedToK.Keys.Contains(k))
                    {
                        if (questionsRelatedToK[k].Count == 0)
                        {
                            questionsRelatedToK.Remove(k);
                            if(questionsRelatedToK.Keys.Count ==0)
                            {
                                return result;
                            }
                            continue;
                        }

                        Question q = questionsRelatedToK[k].First();
                        if(request.Keys.Contains (q.QuestionType ))
                        {
                            if (questionnumbers[q.QuestionType] < request[q.QuestionType])
                            {
                                result.Add(q);
                                questionnumbers[q.QuestionType]++;

                                if (questionnumbers[q.QuestionType] == request[q.QuestionType])
                                {
                                    flags[q.QuestionType] = true;
                                }

                                if(CheckBoolArray(flags.Values .ToArray ()))
                                {
                                    return result;
                                }

                            }
                           
                        }
                        foreach (KeyValuePair<KnowledgePoint, List<Question>> kvp in questionsRelatedToK)
                        {
                            kvp.Value.Remove(q);
                        }
                    }
                }
            }

            return result;
        }
    }

    public class QuestionTypeNumberComparer : IComparer<List<Question>>
    {
        public int Compare(List<Question> l1, List<Question> l2)
        {
            var types1 = from t in l1 select t.QuestionType.Distinct();
            var types2 = from t in l2 select t.QuestionType.Distinct();

            int r1 = types1.Count();
            int r2 = types2.Count();

            if (r1 > r2)
            {
                return 1;
            }
            else if (r1 < r2)
            {
                return -1;
            }
            else
            {
                return l1.Count.CompareTo(l2.Count);
            }

        }
    }

}
